package com.bluesky.objectworld.method.block;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.bluesky.objectworld.ObjectImpl;
import com.bluesky.objectworld._Object;
import com.bluesky.objectworld.method.NativeMethod;
import com.bluesky.objectworld.primitive._Boolean;
import com.bluesky.objectworld.primitive._Integer;
import com.bluesky.objectworld.primitive._String;

/**
 * block is a piece of code. such as if, else, while, switch. a block can
 * contains another block, but variable cannot duplicate.
 * 
 * @author jack
 * 
 */
public abstract class Block extends ObjectImpl {
	Block parent;
	List<Block> children = new ArrayList<Block>();

	// Map<String, _Object> upVariables;
	private Map<String, _Object> localVariables;

	public Block() {
		this.localVariables = new HashMap<String, _Object>();

		NativeMethod declareVariable = new NativeMethod(this, "declareVariable");
		addMethod("declareVariable", declareVariable);

	}

	public _Object declareVariable(_Object name) {
		_String nameStr = (_String) name;
		localVariables.put(nameStr.value, null);
		return null;
	}

	public _Object getVariable(String name) {
		return localVariables.get(name);
	}

	public void updateVariable(String name, _Object obj) {
		localVariables.put(name, obj);
	}

	/**
	 * search variable up to the ancestor.
	 * 
	 * @param name
	 * @return null if not found
	 */
	public Block locateVariableBlock(String name) {
		if (localVariables.containsKey(name))
			return this;
		else {
			if (parent != null)
				return parent.locateVariableBlock(name);
			else
				return null;
		}
	}

	public _Object findVariable(String name) {
		Block b = locateVariableBlock(name);
		if (b != null)
			return b.getVariable(name);
		else
			throw new RuntimeException("variable not found:" + name);
	}

	/**
	 * execute the code in it
	 */
	public abstract void execute();
}
